package zpp_nape.dynamics;
import zpp_nape.Config;
import zpp_nape.Const;
import zpp_nape.util.Flags;
import DummyNapeMain;
import zpp_nape.util.Math;
import zpp_nape.util.Names;
import zpp_nape.util.Pool;
import zpp_nape.util.Lists;
import zpp_nape.shape.Circle;
import zpp_nape.shape.Edge;
import zpp_nape.space.Space;
import zpp_nape.shape.Polygon;
import zpp_nape.shape.Shape;
import zpp_nape.phys.FeatureMix;
import zpp_nape.phys.FluidProperties;
import zpp_nape.phys.Material;
import zpp_nape.phys.Body;
import zpp_nape.geom.AABB;
import zpp_nape.geom.Distance;
import zpp_nape.geom.Mat23;
import zpp_nape.geom.Vec2;
import zpp_nape.geom.VecMath;
import zpp_nape.geom.Collide;
import zpp_nape.dynamics.Arbiter;
import zpp_nape.dynamics.InteractionFilter;
import zpp_nape.constraint.Constraint;
import zpp_nape.dynamics.SpaceArbiterList;
import zpp_nape.constraint.Matrices;
import zpp_nape.constraint.PivotJoint;
import zpp_nape.constraint.WeldJoint;
import nape.util.Flags;
import nape.util.Lists;
import nape.util.Debug;
import nape.space.Space;
import nape.shape.Circle;
import nape.shape.Polygon;
import nape.shape.Edge;
import nape.shape.Shape;
import nape.phys.FluidProperties;
import nape.phys.Material;
import nape.phys.Body;
import nape.geom.AABB;
import nape.geom.Geom;
import nape.geom.Mat23;
import nape.geom.Vec2;
import nape.dynamics.Contact;
import nape.dynamics.Arbiter;
import nape.dynamics.InteractionFilter;
#if swc@:keep#end class ZPP_Contact{
    public var id:Int;
    public var outer:Contact;
    public static var internal:Bool=false;
    public inline function wrapper(){
        if(outer==null){
            internal=true;
            outer=new Contact();
            internal=false;
            outer.zpp_inner=this;
        }
        return outer;
    }
    public var wrap_position:Vec2;
    public function getposition(){
        var me=this;
        wrap_position=new Vec2(inner.px,inner.py);
        wrap_position.zpp_inner.inuse=true;
        wrap_position.zpp_inner.immutable=true;
        wrap_position.zpp_inner._validate=function(){
            if(me.arbiter==null||me.arbiter.cleared)throw "Error: Contact not currently in use";
            {
                me.wrap_position.zpp_inner.x=me.inner.px;
                me.wrap_position.zpp_inner.y=me.inner.py;
                {
                    #if NAPE_ASSERT var res={
                        !({
                            #if flash9 var ret:Bool=untyped __global__["isNaN"](me.wrap_position.zpp_inner.x);
                            ret;
                            #else Math.isNaN(me.wrap_position.zpp_inner.x);
                            #end
                        });
                    };
                    if(!res)throw "assert("+"!assert_isNaN(me.wrap_position.zpp_inner.x)"+") :: "+("vec_set(in n: "+"me.wrap_position.zpp_inner."+",in x: "+"me.inner.px"+",in y: "+"me.inner.py"+")");
                    #end
                };
                {
                    #if NAPE_ASSERT var res={
                        !({
                            #if flash9 var ret:Bool=untyped __global__["isNaN"](me.wrap_position.zpp_inner.y);
                            ret;
                            #else Math.isNaN(me.wrap_position.zpp_inner.y);
                            #end
                        });
                    };
                    if(!res)throw "assert("+"!assert_isNaN(me.wrap_position.zpp_inner.y)"+") :: "+("vec_set(in n: "+"me.wrap_position.zpp_inner."+",in x: "+"me.inner.px"+",in y: "+"me.inner.py"+")");
                    #end
                };
            };
        }
    }
    public var wrap_normal:Vec2;
    public function getnormal(){
        var me=this;
        wrap_normal=new Vec2(inner.nx,inner.ny);
        wrap_position.zpp_inner.inuse=true;
        wrap_normal.zpp_inner.immutable=true;
        wrap_normal.zpp_inner._validate=function(){
            if(me.arbiter==null||me.arbiter.cleared)throw "Error: Contact not currently in use";
            {
                me.wrap_normal.zpp_inner.x=me.inner.nx;
                me.wrap_normal.zpp_inner.y=me.inner.ny;
                {
                    #if NAPE_ASSERT var res={
                        !({
                            #if flash9 var ret:Bool=untyped __global__["isNaN"](me.wrap_normal.zpp_inner.x);
                            ret;
                            #else Math.isNaN(me.wrap_normal.zpp_inner.x);
                            #end
                        });
                    };
                    if(!res)throw "assert("+"!assert_isNaN(me.wrap_normal.zpp_inner.x)"+") :: "+("vec_set(in n: "+"me.wrap_normal.zpp_inner."+",in x: "+"me.inner.nx"+",in y: "+"me.inner.ny"+")");
                    #end
                };
                {
                    #if NAPE_ASSERT var res={
                        !({
                            #if flash9 var ret:Bool=untyped __global__["isNaN"](me.wrap_normal.zpp_inner.y);
                            ret;
                            #else Math.isNaN(me.wrap_normal.zpp_inner.y);
                            #end
                        });
                    };
                    if(!res)throw "assert("+"!assert_isNaN(me.wrap_normal.zpp_inner.y)"+") :: "+("vec_set(in n: "+"me.wrap_normal.zpp_inner."+",in x: "+"me.inner.nx"+",in y: "+"me.inner.ny"+")");
                    #end
                };
            };
        }
    }
    public var arbiter:ZPP_Arbiter;
    public var inner:ZPP_IContact;
    public var pjnAcc:Float;
    public var pjtAcc:Float;
    public var stamp:Int;
    public var hash:Int;
    public var fresh:Bool;
    public var sBias:Float;
    public var dist:Float;
    public function new(){
        inner=new ZPP_IContact();
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function free(){
        arbiter=null;
    }
    static public var zpp_pool:ZPP_Contact;
    public var next:ZPP_Contact;
    #if(flash9&&flib)@:ns("flibdel")#end public inline function elem()return this#if(flash9&&flib)@:ns("flibdel")#end public inline function begin()return next public var inuse:Bool;
    public var modified:Bool;
    public var pushmod:Bool;
    public var mcnt:Int;
    #if(flash9&&flib)@:ns("flibdel")#end public inline function add(o:ZPP_Contact){
        {
            #if NAPE_ASSERT var res={
                o!=null&&!has(o);
            };
            if(!res)throw "assert("+"o!=null&&!has(o)"+") :: "+("add -> "+o);
            #end
        };
        var temp={
            o.inuse=true;
            o;
        };
        temp.next=begin();
        next=temp;
        modified=true;
        mcnt++;
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function addAll(x:ZPP_Contact){
        {
            #if NAPE_ASSERT var res={
                x!=null;
            };
            if(!res)throw "assert("+"x!=null"+") :: "+("addAll -> "+x);
            #end
        };
        {
            var cx_ite=x.begin();
            while(cx_ite!=null){
                var i=cx_ite.elem();
                add(i);
                cx_ite=cx_ite.next;
            }
        };
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function insert(cur:ZPP_Contact,o:ZPP_Contact){
        {
            #if NAPE_ASSERT var res={
                o!=null&&!has(o);
            };
            if(!res)throw "assert("+"o!=null&&!has(o)"+") :: "+("cur -> "+cur+" -> "+o);
            #end
        };
        if(cur==null){
            add(o);
            return begin();
        }
        else{
            var temp={
                o.inuse=true;
                o;
            };
            temp.next=cur.next;
            cur.next=temp;
            pushmod=modified=true;
            mcnt++;
            return temp;
        }
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function pop():Void{
        {
            #if NAPE_ASSERT var res={
                !empty();
            };
            if(!res)throw "assert("+"!empty()"+") :: "+("pop");
            #end
        };
        var ret=begin();
        next=ret.next;
        {
            ret.elem().inuse=false;
        };
        {};
        modified=true;
        mcnt--;
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function pop_unsafe():ZPP_Contact{
        {
            #if NAPE_ASSERT var res={
                !empty();
            };
            if(!res)throw "assert("+"!empty()"+") :: "+("pop_unsafe");
            #end
        };
        var ret=front();
        pop();
        return ret;
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function remove(obj:ZPP_Contact):Bool{
        {
            #if NAPE_ASSERT var res={
                obj!=null&&has(obj);
            };
            if(!res)throw "assert("+"obj!=null&&has(obj)"+") :: "+("remove -> "+obj);
            #end
        };
        var pre=null;
        var cur=begin();
        var ret=false;
        while(cur!=null){
            if(cur.elem()==obj){
                erase(pre);
                ret=true;
                break;
            }
            pre=cur;
            cur=cur.next;
        }
        return ret;
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function erase(pre:ZPP_Contact):ZPP_Contact{
        {
            #if NAPE_ASSERT var res={
                !empty();
            };
            if(!res)throw "assert("+"!empty()"+") :: "+("erase -> "+pre);
            #end
        };
        if(pre==null){
            pop();
            return begin();
        }
        else{
            var old=pre.next;
            var cur=old.next;
            pre.next=cur;
            {
                old.elem().inuse=false;
            };
            {};
            modified=true;
            if(cur==null)pushmod=true;
            mcnt--;
            return cur;
        }
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function splice(pre:ZPP_Contact,n:Int):ZPP_Contact{
        while(n-->0&&pre.next!=null)erase(pre);
        return pre.next;
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function clear(){
        if(false){
            while(!empty()){
                var old=begin();
                next=old.next;
                {
                    old.elem().inuse=false;
                };
                {};
                mcnt--;
            }
            modified=true;
            pushmod=true;
        }
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function reverse(){
        var cur=begin();
        var pre=null;
        while(cur!=null){
            var nx=cur.next;
            cur.next=pre;
            next=cur;
            pre=cur;
            cur=nx;
        }
        modified=true;
        pushmod=true;
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function empty():Bool return begin()==null#if(flash9&&flib)@:ns("flibdel")#end public inline function size(){
        var cnt=0;
        var cur=begin();
        while(cur!=null){
            cnt++;
            cur=cur.next;
        }
        return cnt;
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function has(obj:ZPP_Contact){
        {
            #if NAPE_ASSERT var res={
                obj!=null;
            };
            if(!res)throw "assert("+"obj!=null"+") :: "+("has -> "+obj);
            #end
        };
        return({
            var ret=false;
            {
                var cx_ite=this.begin();
                while(cx_ite!=null){
                    var npite=cx_ite.elem();
                    {
                        if(npite==obj){
                            ret=true;
                            break;
                        }
                    };
                    cx_ite=cx_ite.next;
                }
            };
            ret;
        });
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function front()return begin().elem()#if(flash9&&flib)@:ns("flibdel")#end public inline function back(){
        var ret=begin();
        var cur=ret;
        while(cur!=null){
            ret=cur;
            cur=cur.next;
        }
        return ret.elem();
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function iterator_at(ind:Int){
        {
            #if NAPE_ASSERT var res={
                ind>=-1&&ind<size();
            };
            if(!res)throw "assert("+"ind>=-1&&ind<size()"+") :: "+("iterator_at -> "+ind);
            #end
        };
        var ret=begin();
        while(ind-->0&&ret!=null)ret=ret.next;
        return ret;
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function at(ind:Int){
        {
            #if NAPE_ASSERT var res={
                ind>=0&&ind<size();
            };
            if(!res)throw "assert("+"ind>=0&&ind<size()"+") :: "+("at -> "+ind);
            #end
        };
        var it=iterator_at(ind);
        return if(it!=null)it.elem()else null;
    }
}
#if swc@:keep#end class ZPP_IContact{
    public var id:Int;
    public var active:Bool;
    public var r1x:Float;
    public var r1y:Float;
    public var r2x:Float;
    public var r2y:Float;
    public var nx:Float;
    public var ny:Float;
    public var px:Float;
    public var py:Float;
    public var nMass:Float;
    public var tMass:Float;
    public var bounce:Float;
    public var friction:Float;
    public var bias:Float;
    public var jnAcc:Float;
    public var jtAcc:Float;
    public var jbAcc:Float;
    public function new(){}
    public var next:ZPP_IContact;
    #if(flash9&&flib)@:ns("flibdel")#end public inline function elem()return this#if(flash9&&flib)@:ns("flibdel")#end public inline function begin()return next public var inuse:Bool;
    public var modified:Bool;
    public var pushmod:Bool;
    public var mcnt:Int;
    #if(flash9&&flib)@:ns("flibdel")#end public inline function add(o:ZPP_IContact){
        {
            #if NAPE_ASSERT var res={
                o!=null&&!has(o);
            };
            if(!res)throw "assert("+"o!=null&&!has(o)"+") :: "+("add -> "+o);
            #end
        };
        var temp={
            o.inuse=true;
            o;
        };
        temp.next=begin();
        next=temp;
        modified=true;
        mcnt++;
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function addAll(x:ZPP_IContact){
        {
            #if NAPE_ASSERT var res={
                x!=null;
            };
            if(!res)throw "assert("+"x!=null"+") :: "+("addAll -> "+x);
            #end
        };
        {
            var cx_ite=x.begin();
            while(cx_ite!=null){
                var i=cx_ite.elem();
                add(i);
                cx_ite=cx_ite.next;
            }
        };
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function insert(cur:ZPP_IContact,o:ZPP_IContact){
        {
            #if NAPE_ASSERT var res={
                o!=null&&!has(o);
            };
            if(!res)throw "assert("+"o!=null&&!has(o)"+") :: "+("cur -> "+cur+" -> "+o);
            #end
        };
        if(cur==null){
            add(o);
            return begin();
        }
        else{
            var temp={
                o.inuse=true;
                o;
            };
            temp.next=cur.next;
            cur.next=temp;
            pushmod=modified=true;
            mcnt++;
            return temp;
        }
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function pop():Void{
        {
            #if NAPE_ASSERT var res={
                !empty();
            };
            if(!res)throw "assert("+"!empty()"+") :: "+("pop");
            #end
        };
        var ret=begin();
        next=ret.next;
        {
            ret.elem().inuse=false;
        };
        {};
        modified=true;
        mcnt--;
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function pop_unsafe():ZPP_IContact{
        {
            #if NAPE_ASSERT var res={
                !empty();
            };
            if(!res)throw "assert("+"!empty()"+") :: "+("pop_unsafe");
            #end
        };
        var ret=front();
        pop();
        return ret;
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function remove(obj:ZPP_IContact):Bool{
        {
            #if NAPE_ASSERT var res={
                obj!=null&&has(obj);
            };
            if(!res)throw "assert("+"obj!=null&&has(obj)"+") :: "+("remove -> "+obj);
            #end
        };
        var pre=null;
        var cur=begin();
        var ret=false;
        while(cur!=null){
            if(cur.elem()==obj){
                erase(pre);
                ret=true;
                break;
            }
            pre=cur;
            cur=cur.next;
        }
        return ret;
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function erase(pre:ZPP_IContact):ZPP_IContact{
        {
            #if NAPE_ASSERT var res={
                !empty();
            };
            if(!res)throw "assert("+"!empty()"+") :: "+("erase -> "+pre);
            #end
        };
        if(pre==null){
            pop();
            return begin();
        }
        else{
            var old=pre.next;
            var cur=old.next;
            pre.next=cur;
            {
                old.elem().inuse=false;
            };
            {};
            modified=true;
            if(cur==null)pushmod=true;
            mcnt--;
            return cur;
        }
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function splice(pre:ZPP_IContact,n:Int):ZPP_IContact{
        while(n-->0&&pre.next!=null)erase(pre);
        return pre.next;
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function clear(){
        if(false){
            while(!empty()){
                var old=begin();
                next=old.next;
                {
                    old.elem().inuse=false;
                };
                {};
                mcnt--;
            }
            modified=true;
            pushmod=true;
        }
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function reverse(){
        var cur=begin();
        var pre=null;
        while(cur!=null){
            var nx=cur.next;
            cur.next=pre;
            next=cur;
            pre=cur;
            cur=nx;
        }
        modified=true;
        pushmod=true;
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function empty():Bool return begin()==null#if(flash9&&flib)@:ns("flibdel")#end public inline function size(){
        var cnt=0;
        var cur=begin();
        while(cur!=null){
            cnt++;
            cur=cur.next;
        }
        return cnt;
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function has(obj:ZPP_IContact){
        {
            #if NAPE_ASSERT var res={
                obj!=null;
            };
            if(!res)throw "assert("+"obj!=null"+") :: "+("has -> "+obj);
            #end
        };
        return({
            var ret=false;
            {
                var cx_ite=this.begin();
                while(cx_ite!=null){
                    var npite=cx_ite.elem();
                    {
                        if(npite==obj){
                            ret=true;
                            break;
                        }
                    };
                    cx_ite=cx_ite.next;
                }
            };
            ret;
        });
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function front()return begin().elem()#if(flash9&&flib)@:ns("flibdel")#end public inline function back(){
        var ret=begin();
        var cur=ret;
        while(cur!=null){
            ret=cur;
            cur=cur.next;
        }
        return ret.elem();
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function iterator_at(ind:Int){
        {
            #if NAPE_ASSERT var res={
                ind>=-1&&ind<size();
            };
            if(!res)throw "assert("+"ind>=-1&&ind<size()"+") :: "+("iterator_at -> "+ind);
            #end
        };
        var ret=begin();
        while(ind-->0&&ret!=null)ret=ret.next;
        return ret;
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function at(ind:Int){
        {
            #if NAPE_ASSERT var res={
                ind>=0&&ind<size();
            };
            if(!res)throw "assert("+"ind>=0&&ind<size()"+") :: "+("at -> "+ind);
            #end
        };
        var it=iterator_at(ind);
        return if(it!=null)it.elem()else null;
    }
}
